home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / earcd / mus / play / mikmod.lzh / mikmod / load_stm.c < prev    next >
C/C++ Source or Header  |  1997-01-28  |  9KB  |  380 lines

  1. /*
  2.  
  3. Name:
  4. LOAD_STM.C
  5.  
  6. Description:
  7. ScreamTracker 2 (STM) module Loader - Version 1.oOo Release 2 
  8. A Coding Nightmare by Rao and Air Richter of HaRDCoDE
  9. You can now play all of those wonderful old C.C. Catch STM's!
  10.  
  11. Portability:
  12. All systems - all compilers (hopefully)
  13.  
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include "mikmod.h"
  20.  
  21. typedef struct STMNOTE{
  22.    UBYTE note,insvol,volcmd,cmdinf;
  23. } STMNOTE;
  24.  
  25.  
  26. /* Raw STM sampleinfo struct: */
  27.  
  28. typedef struct STMSAMPLE{
  29.    char  filename[12]; /* Can't have long comments - just filename comments :) */
  30.    char  unused;       /* 0x00 */
  31.    UBYTE instdisk;     /* Instrument disk */
  32.    UWORD reserved;     /* ISA in memory when in ST 2 */
  33.    UWORD length;       /* Sample length */
  34.    UWORD loopbeg;      /* Loop start point */
  35.    UWORD loopend;      /* Loop end point */
  36.    UBYTE volume;       /* Volume */
  37.    UBYTE reserved2;    /* More reserved crap */
  38.    UWORD c2spd;        /* Good old c2spd */
  39.    UBYTE reserved3[4]; /* Yet more of PSi's reserved crap */
  40.    UWORD isa;          /* Internal Segment Address -> */
  41.                        /*    contrary to the tech specs, this is NOT actually */
  42.                        /*    written to the stm file. */
  43. } STMSAMPLE;
  44.  
  45. /* Raw STM header struct: */
  46.  
  47. typedef struct STMHEADER{
  48.    char songname[20];
  49.    char trackername[8];   /* !SCREAM! for ST 2.xx */
  50.    char unused;           /* 0x1A */
  51.    char filetype;         /* 1=song, 2=module (only 2 is supported, of course) :) */
  52.    char ver_major;        /* Like 2 */
  53.    char ver_minor;        /* "ditto" */
  54.    UBYTE inittempo;       /* initspeed= stm inittempo>>4 */
  55.    UBYTE  numpat;         /* number of patterns */
  56.    UBYTE   globalvol;     /* <- WoW! a RiGHT TRiANGLE =8*) */
  57.    UBYTE    reserved[13]; /* More of PSi's internal crap */
  58.    STMSAMPLE sample[31];  /* STM sample data */
  59.    UBYTE patorder[128];   /* Docs say 64 - actually 128 */
  60. } STMHEADER;
  61.  
  62.  
  63. static STMNOTE *stmbuf;
  64. static STMHEADER *mh;
  65.  
  66. char STM_Version[]="Screamtracker 2";
  67.  
  68.  
  69.  
  70. BOOL STM_Test(void)
  71. {
  72.    char str[9],filetype;
  73.  
  74.    _mm_fseek(modfp,21,SEEK_SET);
  75.    fread(str,1,9,modfp);
  76.    fread(&filetype,1,1,modfp);
  77.    if(!memcmp(str,"!SCREAM!",8) || (filetype!=2)) /* STM Module = filetype 2 */
  78.       return 0;
  79.    return 1;
  80. }
  81.  
  82.  
  83.  
  84. BOOL STM_Init(void)
  85. {
  86.     stmbuf=NULL;
  87.     if(!(mh=MyCalloc(1,sizeof(STMHEADER)))) return 0;
  88.     return 1;
  89. }
  90.  
  91. void STM_Cleanup(void)
  92. {
  93.     if(mh!=NULL) free(mh);
  94.     if(stmbuf!=NULL) free(stmbuf);
  95. }
  96.  
  97.  
  98.  
  99. void STM_ConvertNote(STMNOTE *n)
  100. {
  101.     UBYTE note,ins,vol,cmd,inf;
  102.  
  103.     /* extract the various information from the 4 bytes that
  104.        make up a single note */
  105.  
  106.         note=n->note;
  107.         ins=n->insvol>>3;
  108.         vol=(n->insvol&7)+(n->volcmd>>1);
  109.         cmd=n->volcmd&15;
  110.         inf=n->cmdinf;
  111.  
  112.         if(ins!=0 && ins<32){
  113.             UniInstrument(ins-1);
  114.         }
  115.  
  116.       /* special values of [SBYTE0] are handled here -> */
  117.       /* we have no idea if these strange values will ever be encountered */
  118.       /* but it appears as though stms sound correct. */
  119.       if(note==254 || note==252) UniPTEffect(0xc,0); /* <- note off command (???) */
  120.          else
  121.       /* if note < 251, then all three bytes are stored in the file */
  122.       if(note<251) UniNote((((note>>4)+2)*12)+(note&0xf));      /* <- normal note and up the octave by two */
  123.  
  124.         if(vol<65){
  125.             UniPTEffect(0xc,vol);
  126.         }
  127.  
  128.         if(cmd!=255){
  129.             switch(cmd){
  130.  
  131.                 case 1:                 /* Axx set speed to xx and add 0x1c to fix StoOoPiD STM 2.x */
  132.                     UniPTEffect(0xf,inf>>4);
  133.                     break;
  134.  
  135.                 case 2:                 /* Bxx position jump */
  136.                     UniPTEffect(0xb,inf);
  137.                     break;
  138.  
  139.                 case 3:                 /* Cxx patternbreak to row xx */
  140.                     UniPTEffect(0xd,inf);
  141.                     break;
  142.  
  143.                 case 4:                 /* Dxy volumeslide */
  144.                     UniWrite(UNI_S3MEFFECTD);
  145.                     UniWrite(inf);
  146.                     break;
  147.  
  148.                 case 5:                 /* Exy toneslide down */
  149.                     UniWrite(UNI_S3MEFFECTE);
  150.                     UniWrite(inf);
  151.                     break;
  152.  
  153.                 case 6:                 /* Fxy toneslide up */
  154.                     UniWrite(UNI_S3MEFFECTF);
  155.                     UniWrite(inf);
  156.                     break;
  157.  
  158.                 case 7:                 /* Gxx Tone portamento,speed xx */
  159.                     UniPTEffect(0x3,inf);
  160.                     break;
  161.  
  162.                 case 8:                 /* Hxy vibrato */
  163.                     UniPTEffect(0x4,inf);
  164.                     break;
  165.  
  166.                 case 9:                 /* Ixy tremor, ontime x, offtime y */
  167.                     UniWrite(UNI_S3MEFFECTI);
  168.                     UniWrite(inf);
  169.                     break;
  170.  
  171.                 case 0xa:               /* Jxy arpeggio */
  172.                     UniPTEffect(0x0,inf);
  173.                     break;
  174.  
  175.                 case 0xb:               /* Kxy Dual command H00 & Dxy */
  176.                     UniPTEffect(0x4,0);
  177.                     UniWrite(UNI_S3MEFFECTD);
  178.                     UniWrite(inf);
  179.                     break;
  180.  
  181.                 case 0xc:               /* Lxy Dual command G00 & Dxy */
  182.                     UniPTEffect(0x3,0);
  183.                     UniWrite(UNI_S3MEFFECTD);
  184.                     UniWrite(inf);
  185.                     break;
  186.  
  187.         /* Support all these above, since ST2 can LOAD these values */
  188.         /* but can actually only play up to J - and J is only */
  189.         /* half-way implemented in ST2 */
  190.  
  191.                 case 0x18:      /* Xxx amiga command 8xx - What the hell, support panning. :) */
  192.                     UniPTEffect(0x8,inf);
  193.                     break;
  194.             }
  195.         }
  196.  
  197. }
  198.  
  199.  
  200. UBYTE *STM_ConvertTrack(STMNOTE *n)
  201. {
  202.     int t;
  203.  
  204.     UniReset();
  205.     for(t=0;t<64;t++)
  206.     {       STM_ConvertNote(n);
  207.         UniNewline();
  208.         n+=of.numchn;
  209.     }
  210.     return UniDup();
  211. }
  212.  
  213.  
  214.  
  215.  
  216. BOOL STM_LoadPatterns(void)
  217. {
  218.     int t,s,tracks=0;
  219.  
  220.     if(!AllocPatterns()) return 0;
  221.     if(!AllocTracks()) return 0;
  222.  
  223.     /* Allocate temporary buffer for loading
  224.        and converting the patterns */
  225.  
  226.     if(!(stmbuf=MyCalloc(64U*of.numchn,sizeof(STMNOTE)))) return 0;
  227.  
  228.     for(t=0;t<of.numpat;t++){
  229.  
  230.         for(s=0;s<(64U*of.numchn);s++){
  231.             stmbuf[s].note=_mm_read_UBYTE(modfp);
  232.             stmbuf[s].insvol=_mm_read_UBYTE(modfp);
  233.             stmbuf[s].volcmd=_mm_read_UBYTE(modfp);
  234.             stmbuf[s].cmdinf=_mm_read_UBYTE(modfp);
  235.         }
  236.  
  237.         if(feof(modfp)){
  238.             myerr=ERROR_LOADING_PATTERN;
  239.             return 0;
  240.         }
  241.  
  242.         for(s=0;s<of.numchn;s++){
  243.             if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
  244.         }
  245.     }
  246.  
  247.     return 1;
  248. }
  249.  
  250.  
  251.  
  252. BOOL STM_Load(void)
  253. {
  254.     int t;
  255.     ULONG MikMod_ISA; /* We MUST generate our own ISA - NOT stored in the stm */
  256.     INSTRUMENT *d;
  257.     SAMPLE *q;
  258.  
  259.     /* try to read stm header */
  260.  
  261.     _mm_read_str(mh->songname,20,modfp);
  262.     _mm_read_str(mh->trackername,8,modfp);
  263.     mh->unused        =_mm_read_UBYTE(modfp);
  264.     mh->filetype    =_mm_read_UBYTE(modfp);
  265.     mh->ver_major    =_mm_read_UBYTE(modfp);
  266.     mh->ver_minor    =_mm_read_UBYTE(modfp);
  267.     mh->inittempo    =_mm_read_UBYTE(modfp);
  268.     mh->numpat        =_mm_read_UBYTE(modfp);
  269.     mh->globalvol    =_mm_read_UBYTE(modfp);
  270.     _mm_read_UBYTES(mh->reserved,13,modfp);
  271.  
  272.     for(t=0;t<31;t++){
  273.         STMSAMPLE *s=&mh->sample[t];  /* STM sample data */
  274.         _mm_read_str(s->filename,12,modfp);
  275.         s->unused    =_mm_read_UBYTE(modfp);
  276.         s->instdisk    =_mm_read_UBYTE(modfp);
  277.         s->reserved    =_mm_read_I_UWORD(modfp);
  278.         s->length    =_mm_read_I_UWORD(modfp);
  279.         s->loopbeg    =_mm_read_I_UWORD(modfp);
  280.         s->loopend    =_mm_read_I_UWORD(modfp);
  281.         s->volume    =_mm_read_UBYTE(modfp);
  282.         s->reserved2=_mm_read_UBYTE(modfp);
  283.         s->c2spd    =_mm_read_I_UWORD(modfp);
  284.         _mm_read_UBYTES(s->reserved3,4,modfp);
  285.         s->isa        =_mm_read_I_UWORD(modfp);
  286.     }
  287.     _mm_read_UBYTES(mh->patorder,128,modfp);
  288.  
  289.     if(feof(modfp)){
  290.         myerr=ERROR_LOADING_HEADER;
  291.         return 0;
  292.     }
  293.  
  294.     /* set module variables */
  295.  
  296.     of.modtype=strdup(STM_Version);
  297.     of.songname=DupStr(mh->songname,20); /* make a cstr of songname */
  298.  
  299.     of.numpat=mh->numpat;
  300.  
  301.     of.initspeed=6; /* Always this */
  302.  
  303.     /* STM 2.x tempo has always been fucked... The default of 96 */
  304.     /* is actually 124, so we add 1ch to the initial value of 60h */
  305.  
  306.     /* MikMak: No it's not.. STM tempo is UNI speed << 4 */
  307.  
  308.     of.inittempo=125;               /* mh->inittempo+0x1c; */
  309.     of.initspeed=mh->inittempo>>4;
  310.     of.numchn=4; /* get number of channels */
  311.  
  312.     t=0;
  313.     while(mh->patorder[t]!=99){ /* 99 terminates the patorder list */
  314.         of.positions[t]=mh->patorder[t];
  315.         t++;
  316.     }
  317.     of.numpos=--t;
  318.     of.numtrk=of.numpat*of.numchn;
  319.  
  320.     /* Finally, init the sampleinfo structures */
  321.  
  322.     of.numins=31; /* always this */
  323.  
  324.     if(!AllocInstruments()) return 0;
  325.     if(!STM_LoadPatterns()) return 0;
  326.  
  327.     d=of.instruments;
  328.  
  329.     MikMod_ISA=ftell(modfp);
  330.     MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;
  331.  
  332.     for(t=0;t<of.numins;t++){
  333.  
  334.         d->numsmp=1;
  335.         if(!AllocSamples(d)) return 0;
  336.         q=d->samples;
  337.  
  338.         /* load sample info */
  339.  
  340.         d->insname=DupStr(mh->sample[t].filename,12);
  341.         q->c2spd=mh->sample[t].c2spd;
  342.         q->volume=mh->sample[t].volume;
  343.         q->length=mh->sample[t].length;
  344.         if (!mh->sample[t].volume || q->length==1 ) q->length = 0; /* if vol = 0 or length = 1, then no sample */
  345.         q->loopstart=mh->sample[t].loopbeg;
  346.         q->loopend=mh->sample[t].loopend;
  347.         q->seekpos=MikMod_ISA;
  348.  
  349.         MikMod_ISA+=q->length;
  350.  
  351.         MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;
  352.  
  353.       /* Once again, contrary to the STM specs, all the sample data is */
  354.       /* actually SIGNED! Sheesh */
  355.  
  356.         q->flags=SF_SIGNED;
  357.  
  358.         if(mh->sample[t].loopend>0 && mh->sample[t].loopend!=0xffff) q->flags|=SF_LOOP;
  359.  
  360.         /* fix replen if repend>length */
  361.  
  362.         if(q->loopend>q->length) q->loopend=q->length;
  363.  
  364.         d++;
  365.     }
  366.  
  367.     return 1;
  368. }
  369.  
  370.  
  371. LOADER load_stm={
  372.     NULL,
  373.     "STM",
  374.     "Portable STM Loader - V 1.2 - A Coding Nightmare by Rao and Air Richter of HaRDCoDE",
  375.     STM_Init,
  376.     STM_Test,
  377.     STM_Load,
  378.     STM_Cleanup
  379. };
  380.